import { defineStore } from 'pinia'
import { ref } from 'vue'
import { agencyAsync } from '@/appox/appox'
import { appoxUtility } from '@/appox/appox'
import { AppoxPointCloudSample } from '@/appox/appox'
import { isDark } from '@/utils/utility'

export const usePointCloudMonitorStore = defineStore('pointCloudMonitor', () => {
  // 状态
  const channel = ref(parseInt(localStorage.getItem('AppoxJsTest.PointCloudMonitorChannel') || '0'))
  const canvasRef = ref(null)
  
  // 数据
  let pointCloudSampleBuffer = []

  // 视图参数
  const pitch = ref(-20 * Math.PI / 180)  // 俯仰角
  const yaw = ref(0)      // 偏航角
  const fov = ref(60 * Math.PI / 180)    // 视场角
  const trans = ref([0, 0]) // 平移

  // 鼠标交互状态
  const mouseDragStart = ref(null)
  const yawStart = ref(0)
  const pitchStart = ref(0)

  // WebGL相关变量
  let gl, program
  let uPitch, uYaw, uFov, uTrans, uCanvasSize, uNear, uFar
  
  // 缓冲区缓存
  let gridBuffer = null
  let vehicleBuffer = null
  let pointBuffer = null
  let pointBufferSize = 0
  let pointDataArray = null // 预分配的Float32Array

  // 顶点着色器 - 将realToView函数转换为shader
  const vertexShaderSource = `
    attribute vec3 aPosition;
    attribute float aType; // 0: 点云, 1: 网格, 2: 车辆
    
    uniform float uPitch;
    uniform float uYaw;
    uniform float uFov;
    uniform vec2 uTrans;
    uniform vec2 uCanvasSize;
    uniform float uNear;
    uniform float uFar;
    
    varying vec4 vColor;
    
    void main() {
      vec3 pos = aPosition;
      
      // 3D坐标变换和投影
      // 平移
      pos.x += -20.0 * sin(uPitch);
      pos.y += uTrans.x + 20.0 * cos(uPitch) * sin(uYaw);
      pos.z += uTrans.y + 20.0 * cos(uPitch) * cos(uYaw);
      
      // 旋转
      float yawCos = cos(uYaw);
      float yawSin = sin(uYaw);
      float pitchCos = cos(uPitch);
      float pitchSin = sin(uPitch);
      
      vec3 B;
      B.x = pos.x;
      B.y = pos.y * yawCos - pos.z * yawSin;
      B.z = pos.y * yawSin + pos.z * yawCos;
      
      pos.x = B.x * pitchCos + B.z * pitchSin;
      pos.y = B.y;
      pos.z = -B.x * pitchSin + B.z * pitchCos;
      
      // 投影
      float fovTanInv = 1.0 / tan(uFov * 0.5);
      B.x = pos.x * fovTanInv;
      B.y = pos.y * fovTanInv;
      B.z = (pos.z - uNear) * uFar * 0.00333555;
      
      if (pos.z == 0.0) {
        gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
        return;
      }
      
      float k = 1.0 / pos.z;
      if (B.z * k > 1.00065 || B.x * k > 10000.0 || B.y * k > 10000.0) {
        gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
        return;
      }
      
      vec2 screenPos = vec2(
        uCanvasSize.x * 0.5 - 200.0 * B.y * k,
        uCanvasSize.y * 0.5 + 200.0 * B.x * k
      );
      
      // 转换为NDC坐标，保持固定的视野纵横比
      vec2 ndc = (screenPos / uCanvasSize) * 2.0 - 1.0;
      // 修正宽高比，使视野保持固定的纵横比（类似16:9）
      float targetAspectRatio = 16.0 / 9.0;
      float currentAspectRatio = uCanvasSize.x / uCanvasSize.y;
      if (currentAspectRatio > targetAspectRatio) {
        // 如果canvas太宽，在x方向裁剪视野
        ndc.x *= targetAspectRatio / currentAspectRatio;
      }
      gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0);
      
      // 设置点大小（仅对点云有效）
      if (aType < 0.5) {
        gl_PointSize = 1.5;
      }
      
      // 根据类型设置颜色
      if (aType < 0.5) {
        vColor = vec4(1.0, 0.0, 1.0, 1.0); // 点云颜色
      } else if (aType < 1.5) {
        vColor = vec4(0.75, 0.75, 0.75, 1.0); // 网格颜色
      } else {
        vColor = vec4(0.25, 0.75, 0.25, 1.0); // 车辆颜色
      }
    }
  `

  // 片段着色器
  const fragmentShaderSource = `
    precision mediump float;
    varying vec4 vColor;
    
    void main() {
      gl_FragColor = vColor;
    }
  `

  // 初始化WebGL
  function initWebGL() {
    const canvas = canvasRef.value
    if (!canvas) return

    // 调整canvas尺寸 - 宽度跟随容器，高度固定
    const rect = canvas.getBoundingClientRect()
    canvas.width = rect.width
    canvas.height = 450

    // 获取WebGL上下文
    gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl')
    if (!gl) {
      console.error('WebGL not supported')
      return
    }

    // 创建着色器程序
    const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource)
    const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource)
    program = createProgram(gl, vertexShader, fragmentShader)

    if (!program) {
      console.error('Failed to create WebGL program')
      return
    }

    // 获取uniform位置
    uPitch = gl.getUniformLocation(program, 'uPitch')
    uYaw = gl.getUniformLocation(program, 'uYaw')
    uFov = gl.getUniformLocation(program, 'uFov')
    uTrans = gl.getUniformLocation(program, 'uTrans')
    uCanvasSize = gl.getUniformLocation(program, 'uCanvasSize')
    uNear = gl.getUniformLocation(program, 'uNear')
    uFar = gl.getUniformLocation(program, 'uFar')

    // 设置视口
    gl.viewport(0, 0, canvas.width, canvas.height)
    
    // 设置canvas的CSS样式
    canvas.style.width = '100%'
    canvas.style.height = '450px'
    
    // 启用混合
    gl.enable(gl.BLEND)
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
  }

  // 创建着色器
  function createShader(gl, type, source) {
    const shader = gl.createShader(type)
    gl.shaderSource(shader, source)
    gl.compileShader(shader)
    
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      console.error('Shader compilation error:', gl.getShaderInfoLog(shader))
      gl.deleteShader(shader)
      return null
    }
    
    return shader
  }

  // 创建程序
  function createProgram(gl, vertexShader, fragmentShader) {
    const program = gl.createProgram()
    gl.attachShader(program, vertexShader)
    gl.attachShader(program, fragmentShader)
    gl.linkProgram(program)
    
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
      console.error('Program linking error:', gl.getProgramInfoLog(program))
      gl.deleteProgram(program)
      return null
    }
    
    return program
  }

  // 创建缓冲区
  function createBuffer(data) {
    const buffer = gl.createBuffer()
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW)
    return buffer
  }

  // 动作
  function setChannel(newChannel) {
    agencyAsync.removePointCloudReference(channel.value)
    channel.value = newChannel
    localStorage.setItem('AppoxJsTest.PointCloudMonitorChannel', newChannel.toString())
    pointCloudSampleBuffer = [] // 清空点云缓冲区
    agencyAsync.addPointCloudReference(channel.value)
  }

  function setCanvasRef(ref) {
    canvasRef.value = ref
    if (ref) {
      initWebGL()
      
      // 添加窗口大小变化监听
      const resizeObserver = new ResizeObserver(() => {
        if (gl && canvasRef.value) {
          const rect = canvasRef.value.getBoundingClientRect()
          canvasRef.value.width = rect.width
          canvasRef.value.height = 450
          gl.viewport(0, 0, canvasRef.value.width, canvasRef.value.height)
        }
      })
      resizeObserver.observe(ref)
    }
  }
  
  function onConnected() {
    agencyAsync.addPointCloudReference(channel.value)
  }

  function onResetData() {
    pointCloudSampleBuffer = []
    
    // 清理点云缓冲区
    if (pointBuffer) {
      gl.deleteBuffer(pointBuffer)
      pointBuffer = null
      pointBufferSize = 0
    }
    
    // 清理预分配的数组
    pointDataArray = null
  }

  function onInputData(data) {
    if (data instanceof AppoxPointCloudSample) {
      if(data.channel == channel.value) {
        pointCloudSampleBuffer.push(data)
        appoxUtility.clipSampleBuffer(pointCloudSampleBuffer)
      }
    }
  }

  // 鼠标事件处理函数
  function handleMouseDown(e) {
    if (e.buttons !== 1) return // 左键
    const rect = canvasRef.value.getBoundingClientRect()
    mouseDragStart.value = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    }
    yawStart.value = yaw.value
    pitchStart.value = pitch.value
  }

  function handleMouseMove(e) {
    if (!mouseDragStart.value) return
    const rect = canvasRef.value.getBoundingClientRect()
    const mouseX = e.clientX - rect.left
    const mouseY = e.clientY - rect.top
    
    const angle = Math.PI / 180
    yaw.value = yawStart.value + (mouseDragStart.value.x - mouseX) * angle
    pitch.value = pitchStart.value + (mouseDragStart.value.y - mouseY) * angle

    // 限制pitch范围
    if (pitch.value < -90 * angle) pitch.value = -90 * angle
    if (pitch.value > -5 * angle) pitch.value = -5 * angle

    // 限制yaw范围在-180到180度之间
    while (yaw.value > 180 * angle) yaw.value -= 360 * angle
    while (yaw.value < -180 * angle) yaw.value += 360 * angle
  }

  function handleMouseUp() {
    mouseDragStart.value = null
  }

  function handleMouseWheel(e) {
    e.preventDefault() // 阻止默认滚动行为
    if (e.deltaY > 0) {
      fov.value = Math.min(120 * Math.PI / 180, fov.value * 1.05)
    } else {
      fov.value = Math.max(10 * Math.PI / 180, fov.value * 0.95)
    }
  }

  function updateCanvas() {
    if (!gl || !program) {
      return
    }

    let interest = appoxUtility.getInterestTimeLocal()
    if (interest == null) return

    let searchResult = appoxUtility.searchSample(pointCloudSampleBuffer, interest, 1.0)

    const canvas = canvasRef.value
    if (!canvas) return

    // 清空画布 - 恢复原始背景色
    if (isDark) {
      gl.clearColor(0.1, 0.1, 0.1, 1.0)
    }
    else {
      gl.clearColor(0.95, 0.95, 0.95, 1.0)
    }
    gl.clear(gl.COLOR_BUFFER_BIT)

    // 使用着色器程序
    gl.useProgram(program)

    // 设置uniform值
    gl.uniform1f(uPitch, pitch.value)
    gl.uniform1f(uYaw, yaw.value)
    gl.uniform1f(uFov, fov.value)
    gl.uniform2f(uTrans, trans.value[0], trans.value[1])
    gl.uniform2f(uCanvasSize, canvas.width, canvas.height)
    gl.uniform1f(uNear, 0.2)
    gl.uniform1f(uFar, 300.0)

    // 绘制网格
    drawGrid()

    // 绘制车辆
    drawVehicle()

    // 绘制点云
    if (searchResult) {
      let pointCloudSample = searchResult.weight1 > searchResult.weight2 ? searchResult.sample1 : searchResult.sample2
      if (pointCloudSample) {
        drawPointCloud(pointCloudSample)
      }
    }
    
    // 检查WebGL错误
    const error = gl.getError()
    if (error !== gl.NO_ERROR) {
      console.error('WebGL error:', error)
    }
  }

  // 绘制网格
  function drawGrid() {
    // 如果网格缓冲区不存在，创建它
    if (!gridBuffer) {
      const gridData = []
      
      // 横向网格线 - 与原始版本一致
      for (let i = -100; i < 100; i += 10) {
        for (let j = -100; j <= 300; j += 10) {
          gridData.push(0, i, j, 1) // 起点
          gridData.push(0, i + 10, j, 1) // 终点
        }
      }

      // 纵向网格线 - 与原始版本一致
      for (let i = -100; i < 300; i += 10) {
        for (let j = -100; j <= 100; j += 10) {
          gridData.push(0, j, i, 1) // 起点
          gridData.push(0, j, i + 10, 1) // 终点
        }
      }

      gridBuffer = createBuffer(gridData)
      gridBuffer.vertexCount = gridData.length / 4
    }

    const positionLocation = gl.getAttribLocation(program, 'aPosition')
    const typeLocation = gl.getAttribLocation(program, 'aType')
    
    gl.bindBuffer(gl.ARRAY_BUFFER, gridBuffer)
    gl.enableVertexAttribArray(positionLocation)
    gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 16, 0)
    gl.enableVertexAttribArray(typeLocation)
    gl.vertexAttribPointer(typeLocation, 1, gl.FLOAT, false, 16, 12)
    
    gl.drawArrays(gl.LINES, 0, gridBuffer.vertexCount)
  }

  // 绘制车辆
  function drawVehicle() {
    // 如果车辆缓冲区不存在，创建它
    if (!vehicleBuffer) {
      const wid = 1.9
      const len = 4.6
      const triangleLength = Math.min(1.8, len / 3)

      const vehicleData = [
        // 车辆轮廓 - 与原始版本一致
        0, -wid/2, 0, 2, 0, wid/2, 0, 2,
        0, wid/2, 0, 2, 0, wid/2, -len, 2,
        0, wid/2, -len, 2, 0, -wid/2, -len, 2,
        0, -wid/2, -len, 2, 0, -wid/2, 0, 2,
        // 方向指示 - 与原始版本一致
        0, 0, 0, 2, 0, -wid/2, -triangleLength, 2,
        0, 0, 0, 2, 0, wid/2, -triangleLength, 2,
        0, -wid/2, -triangleLength, 2, 0, wid/2, -triangleLength, 2
      ]

      vehicleBuffer = createBuffer(vehicleData)
      vehicleBuffer.vertexCount = vehicleData.length / 4
    }

    const positionLocation = gl.getAttribLocation(program, 'aPosition')
    const typeLocation = gl.getAttribLocation(program, 'aType')
    
    gl.bindBuffer(gl.ARRAY_BUFFER, vehicleBuffer)
    gl.enableVertexAttribArray(positionLocation)
    gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 16, 0)
    gl.enableVertexAttribArray(typeLocation)
    gl.vertexAttribPointer(typeLocation, 1, gl.FLOAT, false, 16, 12)
    
    gl.drawArrays(gl.LINES, 0, vehicleBuffer.vertexCount)
  }

  // 绘制点云
  function drawPointCloud(pointCloudSample) {
    const points = pointCloudSample.pointPositions
    const pointCount = pointCloudSample.pointCount

    if (pointCount === 0) return

    // 如果点云缓冲区不存在或大小不够，创建或重新创建它
    if (!pointBuffer || pointBufferSize < pointCount) {
      if (pointBuffer) {
        gl.deleteBuffer(pointBuffer)
      }
      
      // 创建足够大的预分配数组
      pointDataArray = new Float32Array(Math.max(pointCount * 4, 10000)) // 至少预分配10000个点
      
      // 直接创建Float32Array，避免push操作
      for (let i = 0; i < pointCount; i++) {
        const baseIndex = i * 4
        pointDataArray[baseIndex] = -points[i * 3 + 2] * 0.01     // x
        pointDataArray[baseIndex + 1] = points[i * 3 + 1] * 0.01  // y
        pointDataArray[baseIndex + 2] = points[i * 3] * 0.01      // z
        pointDataArray[baseIndex + 3] = 0                         // type
      }

      pointBuffer = createBuffer(pointDataArray.subarray(0, pointCount * 4))
      pointBufferSize = pointCount
    } else {
      // 更新现有缓冲区数据 - 复用预分配的数组
      gl.bindBuffer(gl.ARRAY_BUFFER, pointBuffer)
      
      // 直接更新预分配的数组，避免创建新的Float32Array
      for (let i = 0; i < pointCount; i++) {
        const baseIndex = i * 4
        pointDataArray[baseIndex] = -points[i * 3 + 2] * 0.01     // x
        pointDataArray[baseIndex + 1] = points[i * 3 + 1] * 0.01  // y
        pointDataArray[baseIndex + 2] = points[i * 3] * 0.01      // z
        pointDataArray[baseIndex + 3] = 0                         // type
      }
      
      gl.bufferSubData(gl.ARRAY_BUFFER, 0, pointDataArray.subarray(0, pointCount * 4))
    }

    const positionLocation = gl.getAttribLocation(program, 'aPosition')
    const typeLocation = gl.getAttribLocation(program, 'aType')
    
    gl.bindBuffer(gl.ARRAY_BUFFER, pointBuffer)
    gl.enableVertexAttribArray(positionLocation)
    gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 16, 0)
    gl.enableVertexAttribArray(typeLocation)
    gl.vertexAttribPointer(typeLocation, 1, gl.FLOAT, false, 16, 12)
    
    gl.drawArrays(gl.POINTS, 0, pointCount)
  }

  return {
    // 状态
    channel,
    canvasRef,
    // 动作
    setChannel,
    setCanvasRef,
    onConnected,
    onResetData,
    onInputData,
    updateCanvas,
    // 鼠标事件处理
    handleMouseDown,
    handleMouseMove,
    handleMouseUp,
    handleMouseWheel
  }
}) 